package com.wsoft.bpm.listener.execute;

import cn.hutool.core.lang.Opt;
import com.wsoft.bpm.service.ActivityCallAble;
import org.activiti.bpmn.model.CallActivity;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.SubProcess;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.ExecutionListener;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 流程结束回调监听器
 *
 * @Author zhonglj
 * @Date 2024-09-23 15:43
 */
@Component("processEndCallBackListener")
public class ProcessEndCallBackListener implements ExecutionListener {
    @Resource
    private RepositoryService repositoryService;

    @Override
    public void notify(DelegateExecution execution) {
        if (isInChildProcess(execution)) {
            // 如果是处于子流程中，不需要操作业务数据
            return;
        }

        ProcessDefinition processDefinition = repositoryService
                .createProcessDefinitionQuery()
                .processDefinitionId(execution.getProcessDefinitionId())
                .singleResult();
        //回调完成
        ActivityCallAble callService = ActivityCallAble.findCallService(processDefinition.getKey());
        if (callService != null) {
            callService.callComplete(processDefinition.getKey(), execution.getProcessInstanceId(), execution.getProcessInstanceBusinessKey());
        }
    }

    public boolean isInChildProcess(DelegateExecution execution) {
        while (execution != null) {
            FlowElement currentFlowElement = execution.getCurrentFlowElement();
            if (currentFlowElement instanceof SubProcess) {
                // 找到一个subProcess，说明在内嵌子流程中
                return true;
            }
            if (currentFlowElement instanceof CallActivity) {
                // 找到一个CallActivity，说明在调用活动中
                return true;
            }

            // 获取父级执行
            String parentExecutionId = Opt.ofNullable(execution.getParentId()).orElse(execution.getSuperExecutionId());
            execution = Context.getCommandContext().getExecutionEntityManager().findById(parentExecutionId);
        }

        return false;
    }
}
